Stage = {
	"Null", 
	"Start",
	"Attack",
	"Aoe",
	"StopAfterCast",
	"StartAfterCast",
	"Max",
}

Stage = CreatEnumTable(Stage, 0)

--stage, timeout, spell
function stageLoop(cbs)
	while true do
		local t, args = coroutine.yield()
		if t == 'stage' then
			return args[1], args[2] 
		end

		local cb = cbs[t]
		if cb then
			local ns = cb(args) 
			if ns then
				return ns 
			end
		end
	end
end

function stageStart() 
	return stageLoop({})
end

function needFindTarget()
	if not UnitExists('target') or UnitIsFriend('player', 'target') or UnitIsDeadOrGhost('target') then
	-- TargetNearestEnemy()
	-- StartAttack()
		-- ut.cast('自动攻击')
		-- print('need find target')
		return true
	end
	return false
end

function stageAttack() 
	local cbs = {}
	cbs.timeout = function ()
		if needFindTarget() then
			return
		end
		ut._attack()
	end
	return stageLoop(cbs)
end

function stageAoe() 
	local cbs = {}
	cbs.timeout = function ()
		if needFindTarget() then
			return
		end
		ut._aoe()
	end
	return stageLoop(cbs)
end


function stageStopAfterCast(spell)
	assert(type(spell)=='string')
	local cbs = {}
	cbs.timeout = function ()
		-- print('cast', spell)
		ut.cast(spell)
	end

	cbs.spell = function(args)
		if spell == args then
			return Stage.Start
		end
	end
	return stageLoop(cbs)
end

function stageStartAfterCast(spell)
	assert(type(spell)=='string')
	local cbs = {}
	cbs.timeout = function ()
		-- print('cast', spell)
		ut.cast(spell)
	end

	cbs.spell = function(args)
		if spell == args then
			return Stage.Attack
		end
	end

	return stageLoop(cbs)
end

-- ut = {} 
function ut._attack()
	print("attack...")
end

function ut._aoe()
	print("aoe...")
end

function ut._interrupt()
	print("interrupt...")
end


stages = {}
stages[Stage.Start] = stageStart
stages[Stage.Attack] = stageAttack
stages[Stage.Aoe] = stageAoe
stages[Stage.StopAfterCast] = stageStopAfterCast
stages[Stage.StartAfterCast] = stageStartAfterCast

stage  = -1
function stageRun()
	stage = Stage.Start
	local args
	while stages[stage] do
		stage, args = stages[stage](args)
	end

	assert(false)
end

-- assert(co == nil)
local co = coroutine.wrap(stageRun)
co()

function ut.sfstart(spell)
	co('stage', {Stage.StartAfterCast, spell, })
end

function ut.sfstop(spell)
	co('stage', {Stage.StopAfterCast, spell, })
end

function ut.attack()
	co('stage', {Stage.Attack, })
end

function ut.interrupt()
	if interruptJudge('target') then
		ut._interrupt()
	end
end


function ut.aoe()
	co('stage', {Stage.Aoe, })
end


function ut.stop()
	co('stage', {Stage.Start, })
end

function ut.onSpell(spell)
	if spell == '自动攻击' then
		return
	end
	print("on spell", spell)
	co('spell', spell)

	if spell == '炉石天马' then
		MoveForwardStart()
	end
end

function ut.onUpdate()
	-- print("on timeout")
	co('timeout')
end
